use std::fmt::Display;

fn main() {
    let p1 = Point { x: 5, y: 4.2 };
    let p2 = Point { x: "hello", y: 'c'};

    println!("p.x() {}", p1.x());

    let p3 = p1.mixup(p2);
    println!("p3:{:?}", p3);

    // p1所有权在调用mixup时被获取
    //println!("p.x() {}", p1.x());
}

// 在结构体中定义泛型
#[derive(Debug)]
struct Point<T, U> {
    x: T,
    y: U,
}

// 在方法上定义泛型, impl后声明泛型
impl<T, U> Point<T, U> {
    fn x(&self) -> &T {
        &self.x
    }

    // 方法上可以声明其他泛型
    fn mixup<V, W>(self, other: Point<V, W>) -> Point<T, W> {
        Point {
            x: self.x,
            y: other.y,
        }
    }
}

// 只为f32这种类型定义方法
impl Point<f32, f32> {
    fn distance_from_origin(&self) -> f32 {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }
}

// 只为trait约束定义方法
impl<T: PartialOrd, U: Display> Point<T, U> {
    
}


/* fn largest<T: PartialOrd>(list: &[T]) -> &T {
    let mut target = &list[0];
    for ele in list.iter() {
        if ele > target {
            target = ele;
        }
    }
    target
} */